use std::collections::{HashMap, HashSet, VecDeque};
use std::fmt;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
use tracing::{debug, error, info};

#[derive(Debug, Clone)]
pub enum Task {
    SSet(String, NoSqlValue),
    SGet(String),
    SRemove(String),
}


#[derive(Debug, Clone)]
pub enum NoSqlValue {
    String(String),
    HashMap(HashMap<String, String>),
    List(VecDeque<NoSqlValue>),
    Set(HashSet<String>),
}

impl fmt::Display for Task {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Task::SSet(key, value) => write!(f, "SSet({}, {})", key, value),
            Task::SGet(key) => write!(f, "SGet({})", key),
            Task::SRemove(key) => write!(f, "SRemove({})", key),
        }
    }
}
impl fmt::Display for NoSqlValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            NoSqlValue::String(s) => write!(f, "{}", s),
            NoSqlValue::HashMap(map) => {
                let entries: Vec<String> = map.iter().map(|(k, v)| format!("{}: {}", k, v)).collect();
                write!(f, "{{{}}}", entries.join(", "))
            }
            NoSqlValue::List(list) => {
                let entries: Vec<String> = list.iter().map(|v| v.to_string()).collect();
                write!(f, "[{}]", entries.join(", "))
            }
            NoSqlValue::Set(set) => {
                let entries: Vec<String> = set.iter().cloned().collect();
                write!(f, "{{{}}}", entries.join(", "))
            }
        }
    }
}

impl fmt::Display for NoSqlDatabase {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let entries: Vec<String> = self.data.iter().map(|(k, v)| format!("{}: {}", k, v)).collect();
        write!(f, "{{{}}}", entries.join(", "))
    }
}

impl NoSqlValue {
    pub fn new_string(value: String) -> Self {
        NoSqlValue::String(value)
    }

    pub fn new_hashmap(value: HashMap<String, String>) -> Self {
        NoSqlValue::HashMap(value)
    }

    pub fn new_list(value: VecDeque<NoSqlValue>) -> Self {
        NoSqlValue::List(value)
    }

    pub fn new_set(value: HashSet<String>) -> Self {
        NoSqlValue::Set(value)
    }
}


#[derive(Debug)]
pub struct NoSqlDatabase {
    data: HashMap<String, NoSqlValue>,
}

impl NoSqlDatabase {
    pub fn new() -> Self {
        NoSqlDatabase {
            data: HashMap::new(),
        }
    }

    // 处理队列中的任务
    pub fn process_task(&mut self, task: Task, tcp_stream: &mut TcpStream) {

        match task {
            Task::SSet(key, value) => {
                debug!("process_task: task: key {} value: {}", key, value);
                self.data.insert(key, value);
            }
            Task::SGet(key) => {
                if let Some(value) = self.data.get(&key) {
                    info!("Retrieved Value: {:?}", value);
                    let response = format!("{}\n", value);
                    let _ = tcp_stream.write_all(response.as_bytes());

                } else {
                    info!("Key not found: {}", key);
                    let _ = tcp_stream.write_all(b"NOT_FOUND\n");
                }
            }
            Task::SRemove(key) => {
                if self.data.remove(&key).is_some() {
                    info!("Removed Key: {}", key);
                } else {
                    info!("Key not found for removal: {}", key);
                }
            }
        }

    }

    // 解析消息为 Task
    pub fn parse_message(message: &str) -> Option<Task> {
        let parts: Vec<&str> = message.split_whitespace().collect();
        match parts.as_slice() {
            ["SSET", key, value] => Some(Task::SSet(key.to_string(), NoSqlValue::new_string(value.to_string()))),
            ["SGET", key] => Some(Task::SGet(key.to_string())),
            ["SREMOVE", key] => Some(Task::SRemove(key.to_string())),
            _ => None,
        }
    }

    pub fn insert(&mut self, key: String, value: NoSqlValue) {
        self.data.insert(key, value);
    }

    pub fn get(&self, key: &str) -> Option<&NoSqlValue> {
        self.data.get(key)
    }

    pub fn remove(&mut self, key: &str) -> Option<NoSqlValue> {
        self.data.remove(key)
    }
}


#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use tracing::info;
    // 注意这个惯用法：在 tests 模块中，从外部作用域导入所有名字。
    use super::*;

    #[test]
    fn test_nosql() {

        // 初始化 NoSQL 数据库
        let mut db = NoSqlDatabase::new();

        // 插入不同类型的数据
        db.insert("name".to_string(), NoSqlValue::new_string("Alice".to_string()));

        let mut address_map = HashMap::new();
        address_map.insert("city".to_string(), "Wonderland".to_string());
        address_map.insert("zip".to_string(), "12345".to_string());
        db.insert("address".to_string(), NoSqlValue::new_hashmap(address_map));

        let mut hobbies_list = VecDeque::new();
        hobbies_list.push_back(NoSqlValue::new_string("Reading".to_string()));
        hobbies_list.push_back(NoSqlValue::new_string("Hiking".to_string()));
        db.insert("hobbies".to_string(), NoSqlValue::new_list(hobbies_list));

        let mut friends_set = HashSet::new();
        friends_set.insert("Bob".to_string());
        friends_set.insert("Charlie".to_string());
        db.insert("friends".to_string(), NoSqlValue::new_set(friends_set));

        // 检索数据
        if let Some(value) = db.get("name") {
            println!("Name: {:?}", value);
        }

        if let Some(value) = db.get("address") {
            println!("Address: {:?}", value);
        }

        if let Some(value) = db.get("hobbies") {
            println!("Hobbies: {:?}", value);
        }

        if let Some(value) = db.get("friends") {
            println!("Friends: {:?}", value);
        }

    }
}